/**********************************************
*  Classes:   CdnRenderer
*  Desc:      Base renderer class. Renders geometry
*  Author:    Vaios Kalpias-Ilias (C) 2008-2009
***********************************************/

#ifndef CDNRENDERER_H
#define CDNRENDERER_H

#include <list>
#include <vector>
#include <windows.h>
#include "Vector.h"
#include "TextureProperty.h"

class SceneNode;
class GeometryNode;
class MaterialProperty;
class TransformNode;
SmartPointer(MaterialProperty);
class Camera;
SmartPointer(Camera);
class SkyBox;
SmartPointer(SkyBox);


class CdnRenderer
{
public:
	
	enum RendererType
	{
		TYPE_OPENGL,
		TYPE_D3D
	};

	// returns single instance
	static CdnRenderer* GetInstance();
	// destroys single instance
	static void Destroy();
	// sets the renderer type
	static void SetType(RendererType type)
	{
		m_eType = type;
	}

	// gets renderer type
	RendererType GetRendererType() const
	{
		return m_eType;
	}

	// initializes renderer
	virtual bool Init(HINSTANCE &hInstance, 
		bool fullscreen = false,
		int width = 1024,
		int height = 768,
		const char* title = "CodenWindow") = 0;

	// render a scene graph
	virtual void RenderScene (SceneNode* scene) = 0;
	// creates vertices, normals etc for a node
	virtual bool BindNodeToMesh(GeometryNode* node,
		mth::Vector3* vertices,
		mth::Vector3* normals,
		mth::Vector2* texCoords,
		int numOfVertices) = 0;

	// gets a texture id
	virtual unsigned int GetNewTextureId() = 0;

	// sets a texture's environment state
	virtual void SetTextureEnvState(unsigned int texId,
		TextureProperty::EnvironmentState state) = 0;

	// resizes window
	virtual void ResizeWindow(int width, int height) = 0;

	// deletes geometry resources
	virtual void UnloadGeometry(){};

	CameraPtr GetCamera() const
	{
		return m_spCamera;
	}

	const HWND& GetHwnd() const
	{
		return m_hWnd;
	}

	const HDC& GetHdc() const
	{
		return m_hDC;
	}

	float GetAspectRatio() const
	{
		return m_fAspectRatio;
	}

	int GetWidth() const
	{
		return m_iWidth;
	}

	int GetHeight() const
	{
		return m_iHeight;
	}

	static int GetMaxLights()
	{
		return 8;
	}

	// setters
	void SetBackgroundColor (const mth::Vector3& color)
	{
		m_vBackgroundColor = color;
	}

	virtual void SetSkyBox (SkyBoxPtr skyBox) = 0;

	void SetDrawBoundingBoxes(bool value)
	{
		m_bDrawBounds = value;
	}

protected:

	// single instance
	static CdnRenderer* m_pInstance;
	// rendering mode / type
	static RendererType m_eType;
	// a camera
	CameraPtr m_spCamera;
	// window dimensions
	int m_iWidth;
	int m_iHeight;

	// background color
	mth::Vector3 m_vBackgroundColor;

	// aspect ratio
	float m_fAspectRatio;

	// was window created
	bool m_bWindowCreated;

	// Fullscreen Flag 
	bool	m_bFullscreen;

	// application HInstance
	HINSTANCE m_hInstance;
	// window handle
	HWND m_hWnd;

	// hdc
	HDC m_hDC;

	// was the renderer initialized
	bool m_bInitialized;

	// draw bounding boxes flag
	bool m_bDrawBounds;

	// window class name
	const char* m_cfClassName;
	
	// a skybox
	SkyBoxPtr m_spSkyBox;

	// ctor - dtor
	CdnRenderer();
	virtual ~CdnRenderer();

	// destroys current window
	virtual void DestroyRenderWindow() = 0;

	// creates window
	virtual bool CreateRendererWindow(HINSTANCE &hInstance, 
		bool fullscreen,
		int width,
		int height,
		const char* title) = 0;

	// tests if an AABB is inside the view frustrum
	bool IsVisible(TransformNode* node);
};

#endif